﻿namespace com.crownpack
{
    using System;
    using System.Linq;

    using com.crownpack.Extensions.DateTimeExtensions;
    using com.crownpack.Extensions.DoubleExtensions;
    using com.crownpack.Extensions.SharePointExtensions;
    using com.crownpack.Extensions.StringExtensions;

    using Microsoft.SharePoint;

    public class Initiative
    {
        #region Fields

        string _Address1;
        bool? _Archived;
        string _Branch;
        string _BranchManager;
        string _BranchName;
        int? _CalendarDaysRemaining;
        int? _CalendarMonthsRemainingInCurrentYear;
        string _City;
        string _CostSavingsType;
        DateTime? _CreatedDate;
        Customer _CustomerValue;
        int _DaysInProcess;
        int _DaysOld;
        int? _DaysProcessedDaysProposed;
        int? _DaysProposed;
        string _DivisionCode;
        double? _EAU;
        double? _EstimatedTotalMonthlySavings;
        double? _EstimatedTotalSavings;
        double? _EstimatedTotalSavingsTotal;
        DateTime? _ExpirationDate;
        int? _FutureRealDaysRemaining;
        int? _FutureRealMonthsRemaining;
        string _GroupCode;
        DateTime? _ImplementationDate;
        bool? _ImplementationStatus;
        string _InitiativeNo;
        int? _InitiativeTimeFrame;
        DateTime? _InProcessDate;
        bool? _InProcessStatus;
        DateTime? _LastModifiedDate;
        string _LocationName;
        int? _LocationNo;
        string _ManagerEMail;
        string _NA_ManagerEmailAddress;
        string _NA_ManagerName;
        string _NA_ManagerNo;
        string _NA_ManagerPhone;
        DateTime? _Now;
        string _ParentCustomerName;
        int? _ParentCustomerNo;
        DateTime? _ProposedDate;
        bool? _ProposedStatus;
        double? _RealizationBalance;
        double? _RealizationBalance2;
        DateTime? _RejectionDate;
        string _RejectionReason;
        string _RejectionReason_;
        double? _RemainingCurrentYearBalance;
        double? _RemainingInitiativeBalance;
        string _Salesrep;
        string _SalesrepEmailAddress;
        string _SalesrepName;
        string _SalesrepPhone;
        string _SectorCode;
        string _St;
        string _Status;
        double? _UnitSavings;
        DateTime? _YearEnd;
        string _Zip;

        #endregion Fields

        #region Constructors

        public Initiative( SPListItem item, SPEventType eventType )
        {
            spListItem = item;
            spEventType = eventType;
        }

        #endregion Constructors

        #region Properties

        public string Address1
        {
            get
            {
                if ( string.IsNullOrEmpty( _Address1 ) )
                {
                    if ( CustomerValue != null )
                        _Address1 = CustomerValue.Address1;
                    else
                    {
                        _Address1 = spListItem.GetValue<string>( Column.Address1 );
                        if ( string.IsNullOrEmpty( _Address1 ) )
                            _Address1 = string.Empty;
                    }
                }
                return _Address1;
            }
        }

        public bool Archived
        {
            get
            {
                if ( !_Archived.HasValue )
                {
                    _Archived = spListItem.GetValue<bool?>( Column.Archived );
                    if ( !_Archived.HasValue || !_Archived.Value )
                    {
                        if ( Status.Equals( com.crownpack.Status.Rejected, StringComparison.OrdinalIgnoreCase ) )
                            _Archived = true;
                        else
                            if ( ExpirationDate.HasValue && LastModifiedDate > ExpirationDate.Value.Date )
                                _Archived = true;
                    }
                }
                return _Archived.Value;
            }
        }

        public string Branch
        {
            get
            {
                if ( string.IsNullOrEmpty( _Branch ) )
                {
                    if ( CustomerValue != null )
                        _Branch = CustomerValue.Branch;
                    else
                    {
                        _Branch = spListItem.GetValue<string>( Column.Branch );
                        if ( string.IsNullOrEmpty( _Branch ) )
                            _Branch = string.Empty;
                    }
                }
                return _Branch;
            }
        }

        public string BranchManager
        {
            get
            {
                if ( string.IsNullOrEmpty( _BranchManager ) )
                {
                    if ( CustomerValue != null )
                        _BranchManager = CustomerValue.BranchManager;
                    else
                    {
                        _BranchManager = spListItem.GetValue<string>( Column.BranchManager );
                        if ( string.IsNullOrEmpty( _BranchManager ) )
                            _BranchManager = string.Empty;
                    }
                }
                return _BranchManager;
            }
        }

        public string BranchName
        {
            get
            {
                if ( string.IsNullOrEmpty( _BranchName ) )
                {
                    if ( CustomerValue != null )
                        _BranchName = CustomerValue.BranchName;
                    else
                    {
                        _BranchName = spListItem.GetValue<string>( Column.BranchName );
                        if ( string.IsNullOrEmpty( _BranchName ) )
                            _BranchName = string.Empty;
                    }
                }
                return _BranchName;
            }
        }

        public int CalendarDaysRemaining
        {
            get
            {
                if ( !_CalendarDaysRemaining.HasValue )
                    _CalendarDaysRemaining = ( ( YearEnd - LastModifiedDate ).TotalDays ).ToInt32( );
                return _CalendarDaysRemaining.HasValue ? _CalendarDaysRemaining.Value : 0;
            }
        }

        public int CalendarMonthsRemainingInCurrentYear
        {
            get
            {
                if ( !_CalendarMonthsRemainingInCurrentYear.HasValue )
                    _CalendarMonthsRemainingInCurrentYear = ( ( YearEnd - LastModifiedDate ).TotalDays / 30 ).ToInt32( );
                return _CalendarMonthsRemainingInCurrentYear.HasValue ? _CalendarMonthsRemainingInCurrentYear.Value : 0;
            }
        }

        public string City
        {
            get
            {
                if ( string.IsNullOrEmpty( _City ) )
                {
                    if ( CustomerValue != null )
                        _City = CustomerValue.City;
                    else
                    {
                        _City = spListItem.GetValue<string>( Column.City );
                        if ( string.IsNullOrEmpty( _City ) )
                            _City = string.Empty;
                    }
                }
                return _City;
            }
        }

        public string CostSavingsType
        {
            get
            {
                if ( string.IsNullOrEmpty( _CostSavingsType ) )
                {
                    if ( spListItem.ContentType.Name.Contains( '-' ) )
                    {
                        string[ ] s = spListItem.ContentType.Name.Split( new string[ ] { "-" }, StringSplitOptions.RemoveEmptyEntries );
                        _CostSavingsType = s[ 0 ].Trim( );
                    }
                    else
                    {
                        _CostSavingsType = spListItem.GetValue<string>( Column.CostSavingsType );
                        if ( string.IsNullOrEmpty( _CostSavingsType ) )
                            _CostSavingsType = spListItem.ContentType.Name;
                    }
                }
                return _CostSavingsType;
            }
        }

        public int DaysInProcess
        {
            get
            {
                if ( InProcessStatus && InProcessDate.HasValue && LastModifiedDate != InProcessDate.Value.Date )
                    _DaysInProcess = ( ( LastModifiedDate - InProcessDate.Value.Date ).TotalDays ).ToInt32( );
                else if ( !InProcessStatus )
                    _DaysInProcess = 0;
                return _DaysInProcess;
            }
        }

        public int DaysOld
        {
            get
            {
                _DaysOld = ( ( LastModifiedDate - CreatedDate ).TotalDays ).ToInt32( );
                return _DaysOld;
            }
        }

        public int DaysProcessedDaysProposed
        {
            get
            {
                if ( !_DaysProcessedDaysProposed.HasValue )
                    _DaysProcessedDaysProposed = DaysInProcess + DaysProposed;
                return _DaysProcessedDaysProposed.HasValue ? _DaysProcessedDaysProposed.Value : 0;
            }
        }

        public int DaysProposed
        {
            get
            {
                if ( ProposedStatus && ProposedDate.HasValue )
                    _DaysProposed = ( ( LastModifiedDate - ProposedDate.Value.Date ).TotalDays ).ToInt32( );
                else
                    _DaysProposed = 0;
                return _DaysProposed.Value;
            }
        }

        public string DivisionCode
        {
            get
            {
                if ( string.IsNullOrEmpty( _DivisionCode ) )
                {
                    if ( CustomerValue != null )
                        _DivisionCode = CustomerValue.DivisionCode;
                    else
                    {
                        _DivisionCode = spListItem.GetValue<string>( Column.DivisionCode );
                        if ( string.IsNullOrEmpty( _DivisionCode ) )
                            _DivisionCode = string.Empty;
                    }
                }
                return _DivisionCode;
            }
        }

        public double EAU
        {
            get
            {
                if ( !_EAU.HasValue )
                    _EAU = spListItem.GetValue<double?>( Column.EAU );
                return _EAU.HasValue ? _EAU.Value : 0;
            }
        }

        public double EstimatedTotalMonthlySavings
        {
            get
            {
                if ( !_EstimatedTotalMonthlySavings.HasValue )
                    _EstimatedTotalMonthlySavings = EstimatedTotalSavingsTotal / InitiativeTimeFrame;
                return _EstimatedTotalMonthlySavings.HasValue ? _EstimatedTotalMonthlySavings.Value : 0;
            }
        }

        public double EstimatedTotalSavings
        {
            get
            {
                if ( !_EstimatedTotalSavings.HasValue )
                    _EstimatedTotalSavings = UnitSavings * EAU;
                return _EstimatedTotalSavings.HasValue ? _EstimatedTotalSavings.Value : 0;
            }
        }

        public double EstimatedTotalSavingsTotal
        {
            get
            {
                _EstimatedTotalSavingsTotal = spListItem.GetValue<double?>( Column.EstimatedTotalSavingsTotal );
                if ( !_EstimatedTotalSavingsTotal.HasValue || _EstimatedTotalSavingsTotal.Value <= 0 )
                    _EstimatedTotalSavingsTotal = EstimatedTotalSavings;
                return _EstimatedTotalSavingsTotal.HasValue ? _EstimatedTotalSavingsTotal.Value : 0;
            }
        }

        public DateTime? ExpirationDate
        {
            get
            {
                if ( RealizationDate.HasValue )
                    _ExpirationDate = RealizationDate.Value.Date.AddMonths( InitiativeTimeFrame );
                return _ExpirationDate;
            }
        }

        public int FutureRealDaysRemaining
        {
            get
            {
                if ( !_FutureRealDaysRemaining.HasValue )
                {
                    if ( RealizationDate.HasValue )
                        _FutureRealDaysRemaining = ( YearEnd - RealizationDate.Value.Date ).TotalDays.ToInt32( );
                }
                return _FutureRealDaysRemaining.HasValue ? _FutureRealDaysRemaining.Value : 0;
            }
        }

        public int FutureRealMonthsRemaining
        {
            get
            {
                if ( !_FutureRealMonthsRemaining.HasValue )
                {
                    if ( RealizationDate.HasValue )
                        _FutureRealMonthsRemaining = ( ( YearEnd - RealizationDate.Value.Date ).TotalDays / 30 ).ToInt32( );
                }
                return _FutureRealMonthsRemaining.HasValue ? _FutureRealMonthsRemaining.Value : 0;
            }
        }

        public string GroupCode
        {
            get
            {
                if ( string.IsNullOrEmpty( _GroupCode ) )
                {
                    if ( CustomerValue != null )
                        _GroupCode = CustomerValue.GroupCode;
                    else
                    {
                        _GroupCode = spListItem.GetValue<string>( Column.GroupCode );
                        if ( string.IsNullOrEmpty( _GroupCode ) )
                            _GroupCode = string.Empty;
                    }
                }
                return _GroupCode;
            }
        }

        public DateTime? ImplementationDate
        {
            get
            {
                if ( !_ImplementationDate.HasValue )
                    if ( ImplementationStatus )
                        _ImplementationDate = Now;
                return _ImplementationDate;
            }
        }

        public bool ImplementationStatus
        {
            get
            {
                _ImplementationStatus = Status.Equals( com.crownpack.Status.Implemented );
                return _ImplementationStatus.Value;
            }
        }

        public string InitiativeNo
        {
            get
            {
                if ( string.IsNullOrEmpty( _InitiativeNo ) )
                    _InitiativeNo = spListItem.GetValue<string>( Column.InitiativeNo );
                if ( string.IsNullOrEmpty( _InitiativeNo ) )
                    _InitiativeNo = string.Format( "{0}-{1:000000}", ParentCustomerNo, spListItem.ID );
                return _InitiativeNo;
            }
        }

        public int InitiativeTimeFrame
        {
            get
            {
                if ( !_InitiativeTimeFrame.HasValue )
                {
                    _InitiativeTimeFrame = spListItem.GetValue<int?>( Column.InitiativeTimeFrame );
                    if ( !_InitiativeTimeFrame.HasValue )
                        _InitiativeTimeFrame = 12;
                }
                return _InitiativeTimeFrame.Value;
            }
        }

        public DateTime? InProcessDate
        {
            get
            {
                if ( !_InProcessDate.HasValue )
                    if ( InProcessStatus )
                        _InProcessDate = Now;
                return _InProcessDate;
            }
        }

        public bool InProcessStatus
        {
            get
            {
                _InProcessStatus = Status.Equals( com.crownpack.Status.InProcess, StringComparison.OrdinalIgnoreCase );
                return _InProcessStatus.Value;
            }
        }

        public string LocationName
        {
            get
            {
                if ( string.IsNullOrEmpty( _LocationName ) )
                {
                    if ( CustomerValue != null )
                        _LocationName = CustomerValue.LocationName;
                    else
                    {
                        _LocationName = spListItem.GetValue<string>( Column.LocationName );
                        if ( string.IsNullOrEmpty( _LocationName ) )
                            _LocationName = string.Empty;
                    }
                }
                return _LocationName;
            }
        }

        public int LocationNo
        {
            get
            {
                if ( !_LocationNo.HasValue )
                {
                    if ( CustomerValue != null )
                        _LocationNo = CustomerValue.LocationNo;
                    else
                        _LocationNo = spListItem.GetValue<string>( Column.LocationNo ).ToNullableInt32( );
                }
                return _LocationNo.HasValue ? _LocationNo.Value : 0;
            }
        }

        public string ManagerEMail
        {
            get
            {
                if ( string.IsNullOrEmpty( _ManagerEMail ) )
                {
                    if ( CustomerValue != null )
                        _ManagerEMail = CustomerValue.ManagerEMail;
                    else
                    {
                        _ManagerEMail = spListItem.GetValue<string>( Column.ManagerEMail );
                        if ( string.IsNullOrEmpty( _ManagerEMail ) )
                            _ManagerEMail = string.Empty;
                    }
                }
                return _ManagerEMail;
            }
        }

        public string NA_ManagerEmailAddress
        {
            get
            {
                if ( string.IsNullOrEmpty( _NA_ManagerEmailAddress ) )
                {
                    if ( CustomerValue != null )
                        _NA_ManagerEmailAddress = CustomerValue.NA_ManagerEmailAddress;
                    else
                    {
                        _NA_ManagerEmailAddress = spListItem.GetValue<string>( Column.NA_ManagerEmailAddress );
                        if ( string.IsNullOrEmpty( _NA_ManagerEmailAddress ) )
                            _NA_ManagerEmailAddress = string.Empty;
                    }
                }
                return _NA_ManagerEmailAddress;
            }
        }

        public string NA_ManagerName
        {
            get
            {
                if ( string.IsNullOrEmpty( _NA_ManagerName ) )
                {
                    if ( CustomerValue != null )
                        _NA_ManagerName = CustomerValue.NA_ManagerName;
                    else
                    {
                        _NA_ManagerName = spListItem.GetValue<string>( Column.NA_ManagerName );
                        if ( string.IsNullOrEmpty( _NA_ManagerName ) )
                            _NA_ManagerName = string.Empty;
                    }
                }
                return _NA_ManagerName;
            }
        }

        public string NA_ManagerNo
        {
            get
            {
                if ( string.IsNullOrEmpty( _NA_ManagerNo ) )
                {
                    if ( CustomerValue != null )
                        _NA_ManagerNo = CustomerValue.NA_ManagerNo;
                    else
                    {
                        _NA_ManagerNo = spListItem.GetValue<string>( Column.NA_ManagerNo );
                        if ( string.IsNullOrEmpty( _NA_ManagerNo ) )
                            _NA_ManagerNo = string.Empty;
                    }
                }
                return _NA_ManagerNo;
            }
        }

        public string NA_ManagerPhone
        {
            get
            {
                if ( string.IsNullOrEmpty( _NA_ManagerPhone ) )
                {
                    if ( CustomerValue != null )
                        _NA_ManagerPhone = CustomerValue.NA_ManagerPhone;
                    else
                    {
                        _NA_ManagerPhone = spListItem.GetValue<string>( Column.NA_ManagerPhone );
                        if ( string.IsNullOrEmpty( _NA_ManagerPhone ) )
                            _NA_ManagerPhone = string.Empty;
                    }
                }
                return _NA_ManagerPhone;
            }
        }

        public string ParentCustomerName
        {
            get
            {
                if ( string.IsNullOrEmpty( _ParentCustomerName ) )
                {
                    if ( CustomerValue != null )
                        _ParentCustomerName = CustomerValue.ParentCustomerName;
                    else
                    {
                        _ParentCustomerName = spListItem.GetValue<string>( Column.ParentCustomerName );
                        if ( string.IsNullOrEmpty( _ParentCustomerName ) )
                            _ParentCustomerName = string.Empty;
                    }
                }
                return _ParentCustomerName;
            }
        }

        public int ParentCustomerNo
        {
            get
            {
                if ( !_ParentCustomerNo.HasValue )
                {
                    if ( CustomerValue != null )
                        _ParentCustomerNo = CustomerValue.ParentCustomerNo;
                    else
                        _ParentCustomerNo = spListItem.GetValue<string>( Column.ParentCustomerNo ).ToNullableInt32( );
                }
                return _ParentCustomerNo.HasValue ? _ParentCustomerNo.Value : 0;
            }
        }

        public DateTime? ProposedDate
        {
            get
            {
                if ( !_ProposedDate.HasValue )
                    if ( ProposedStatus )
                        _ProposedDate = Now;
                return _ProposedDate;
            }
        }

        public bool ProposedStatus
        {
            get
            {
                _ProposedStatus = Status.Equals( com.crownpack.Status.Proposed, StringComparison.OrdinalIgnoreCase );
                return _ProposedStatus.Value;
            }
        }

        public double RealizationBalance
        {
            get
            {
                if ( !_RealizationBalance.HasValue )
                    if ( ExpirationDate.HasValue )
                        _RealizationBalance = ( ( ExpirationDate.Value.Date - LastModifiedDate ).TotalDays / 30 ) * ( EstimatedTotalSavingsTotal / InitiativeTimeFrame );
                    else
                        _RealizationBalance = 0;
                return _RealizationBalance.Value;
            }
        }

        public double RealizationBalance2
        {
            get
            {
                if ( !_RealizationBalance2.HasValue )
                    if ( ExpirationDate.HasValue )
                        _RealizationBalance2 = ( ( ExpirationDate.Value.Date - LastModifiedDate ).TotalDays / 30 ) * ( EstimatedTotalSavings / InitiativeTimeFrame );
                    else
                        _RealizationBalance2 = 0;
                return _RealizationBalance2.Value;
            }
        }

        public DateTime? RealizationDate
        {
            get
            {
                return spListItem.GetValue<DateTime?>( Column.RealizationDate );
            }
        }

        public DateTime? RejectionDate
        {
            get
            {
                if ( !_RejectionDate.HasValue )
                    _RejectionDate = spListItem.GetValue<DateTime?>( Column.RejectionDate );
                if ( !_RejectionDate.HasValue && !string.IsNullOrEmpty( RejectionReason ) )
                    _RejectionDate = DateTime.Now.Date;
                return _RejectionDate;
            }
        }

        public string RejectionReason
        {
            get
            {
                if ( string.IsNullOrEmpty( _RejectionReason ) )
                {
                    SPFieldMultiLineText v = spListItem.Fields.GetField( Column.RejectionReason ) as SPFieldMultiLineText;
                    _RejectionReason = v.GetFieldValueAsText( spListItem[ Column.RejectionReason ] );
                }
                return _RejectionReason;
            }
        }

        public string RejectionReason_
        {
            get
            {
                if ( string.IsNullOrEmpty( _RejectionReason_ ) )
                {
                    _RejectionReason_ = spListItem.GetValue<string>( Column.RejectionReason_ );

                    if ( string.IsNullOrEmpty( _RejectionReason_ ) || string.IsNullOrEmpty( _RejectionReason_.Trim( ) ) )
                        _RejectionReason_ = RejectionReason;
                }
                return _RejectionReason;
            }
        }

        public double RemainingCurrentYearBalance
        {
            get
            {
                if ( !_RemainingCurrentYearBalance.HasValue )
                    if ( ExpirationDate.HasValue && ExpirationDate.Value > YearEnd )
                    {
                        if ( RealizationDate.HasValue && RealizationDate.Value.Date > YearEnd )
                            _RemainingCurrentYearBalance = 0;
                        else
                        {
                            if ( RealizationDate.HasValue && RealizationDate.Value.Date > LastModifiedDate )
                                _RemainingCurrentYearBalance = FutureRealMonthsRemaining * EstimatedTotalMonthlySavings;
                            else
                                _RemainingCurrentYearBalance = CalendarMonthsRemainingInCurrentYear * EstimatedTotalMonthlySavings;
                        }
                    }
                    else
                        _RemainingCurrentYearBalance = RemainingInitiativeBalance;
                return _RemainingCurrentYearBalance.Value;
            }
        }

        public double RemainingInitiativeBalance
        {
            get
            {
                if ( !_RemainingInitiativeBalance.HasValue )
                {
                    if ( EAU <= 0 )
                    {
                        if ( RealizationBalance >= EstimatedTotalSavingsTotal )
                            _RemainingInitiativeBalance = EstimatedTotalSavingsTotal;
                        else
                            _RemainingInitiativeBalance = RealizationBalance;
                    }
                    else
                    {
                        if ( RealizationBalance2 > EstimatedTotalSavings )
                            _RemainingInitiativeBalance = EstimatedTotalSavings;
                        else
                            _RemainingInitiativeBalance = RealizationBalance2;
                    }
                }
                return _RemainingInitiativeBalance.Value;
            }
        }

        public string Salesrep
        {
            get
            {
                if ( string.IsNullOrEmpty( _Salesrep ) )
                {
                    if ( CustomerValue != null )
                        _Salesrep = CustomerValue.Salesrep;
                    else
                    {
                        _Salesrep = spListItem.GetValue<string>( Column.Salesrep );
                        if ( string.IsNullOrEmpty( _Salesrep ) )
                            _Salesrep = string.Empty;
                    }
                }
                return _Salesrep;
            }
        }

        public string SalesrepEmailAddress
        {
            get
            {
                if ( string.IsNullOrEmpty( _SalesrepEmailAddress ) )
                {
                    if ( CustomerValue != null )
                        _SalesrepEmailAddress = CustomerValue.SalesrepEmailAddress;
                    else
                    {
                        _SalesrepEmailAddress = spListItem.GetValue<string>( Column.SalesrepEmailAddress );
                        if ( string.IsNullOrEmpty( _SalesrepEmailAddress ) )
                            _SalesrepEmailAddress = string.Empty;
                    }
                }
                return _SalesrepEmailAddress;
            }
        }

        public string SalesrepName
        {
            get
            {
                if ( string.IsNullOrEmpty( _SalesrepName ) )
                {
                    if ( CustomerValue != null )
                        _SalesrepName = CustomerValue.SalesrepName;
                    else
                    {
                        _SalesrepName = spListItem.GetValue<string>( Column.SalesrepName );
                        if ( string.IsNullOrEmpty( _SalesrepName ) )
                            _SalesrepName = string.Empty;
                    }
                }
                return _SalesrepName;
            }
        }

        public string SalesrepPhone
        {
            get
            {
                if ( string.IsNullOrEmpty( _SalesrepPhone ) )
                {
                    if ( CustomerValue != null )
                        _SalesrepPhone = CustomerValue.SalesrepPhone;
                    else
                    {
                        _SalesrepPhone = spListItem.GetValue<string>( Column.SalesrepPhone );
                        if ( string.IsNullOrEmpty( _SalesrepPhone ) )
                            _SalesrepPhone = string.Empty;
                    }
                }
                return _SalesrepPhone;
            }
        }

        public string SectorCode
        {
            get
            {
                if ( string.IsNullOrEmpty( _SectorCode ) )
                {
                    if ( CustomerValue != null )
                        _SectorCode = CustomerValue.SectorCode;
                    else
                    {
                        _SectorCode = spListItem.GetValue<string>( Column.SectorCode );
                        if ( string.IsNullOrEmpty( _SectorCode ) )
                            _SectorCode = string.Empty;
                    }
                }
                return _SectorCode;
            }
        }

        public string St
        {
            get
            {
                if ( string.IsNullOrEmpty( _St ) )
                {
                    if ( CustomerValue != null )
                        _St = CustomerValue.St;
                    else
                    {
                        _St = spListItem.GetValue<string>( Column.St );
                        if ( string.IsNullOrEmpty( _St ) )
                            _St = string.Empty;
                    }
                }
                return _St;
            }
        }

        public string Status
        {
            get
            {
                if ( string.IsNullOrEmpty( _Status ) )
                {
                    if ( RejectionDate.HasValue && !string.IsNullOrEmpty( RejectionReason ) )
                        _Status = com.crownpack.Status.Rejected;
                    else
                    {
                        if ( spListItem.ContentType.Name.Contains( '-' ) )
                        {
                            string[ ] s = spListItem.ContentType.Name.Split( new string[ ] { "-" }, StringSplitOptions.RemoveEmptyEntries );
                            _Status = s[ s.Length - 1 ].Trim( );
                        }
                        else
                        {
                            _Status = spListItem.GetValue<string>( Column.Status );
                            if ( string.IsNullOrEmpty( _Status ) )
                                _Status = com.crownpack.Status.Unknown;
                        }
                    }
                }
                return _Status;
            }
        }

        public double UnitSavings
        {
            get
            {
                if ( !_UnitSavings.HasValue )
                {
                    _UnitSavings = spListItem.GetValue<double?>( Column.UnitSavings );
                    if ( !_UnitSavings.HasValue )
                        _UnitSavings = 0;
                    if ( EAU > 0 )
                        if ( _UnitSavings <= 0 )
                        {
                            _UnitSavings = EstimatedTotalSavingsTotal / EAU;
                        }
                }
                return _UnitSavings.Value;
            }
        }

        public string Zip
        {
            get
            {
                if ( string.IsNullOrEmpty( _Zip ) )
                {
                    if ( CustomerValue != null )
                        _Zip = CustomerValue.Zip;
                    else
                    {
                        _Zip = spListItem.GetValue<string>( Column.Zip );
                        if ( string.IsNullOrEmpty( _Zip ) )
                            _Zip = string.Empty;
                    }
                }
                return _Zip;
            }
        }

        DateTime CreatedDate
        {
            get
            {
                if ( !_CreatedDate.HasValue )
                    _CreatedDate = spListItem.GetCreatedDate( ).Date;
                return _CreatedDate.Value;
            }
        }

        Customer CustomerValue
        {
            get
            {
                if ( _CustomerValue == null )
                {

                    CustomerFieldValue v = new CustomerFieldValue( spListItem[ Column.Location ], spListItem.Web.Url );
                    _CustomerValue = v.UnderlyingObject;
                }
                return _CustomerValue;
            }
        }

        DateTime LastModifiedDate
        {
            get
            {
                if ( !_LastModifiedDate.HasValue )
                    _LastModifiedDate = spListItem.GetLastModifiedDate( ).Date;
                return _LastModifiedDate.Value;
            }
        }

        DateTime Now
        {
            get
            {
                if ( !_Now.HasValue )
                    _Now = DateTime.Now.Date;
                return _Now.Value;
            }
        }

        SPEventType spEventType
        {
            get;
            set;
        }

        SPListItem spListItem
        {
            get;
            set;
        }

        DateTime YearEnd
        {
            get
            {
                if ( !_YearEnd.HasValue )
                    _YearEnd = DateTime.Now.GetAbsoluteEndOfYear( ).Date;
                return _YearEnd.Value;
            }
        }

        #endregion Properties

        #region Methods

        public void SystemUpdate( )
        {
            spListItem.SetValue( Column.Address1, Address1 );
            spListItem.SetValue( Column.Archived, Archived );
            spListItem.SetValue( Column.Branch, Branch );
            spListItem.SetValue( Column.BranchManager, BranchManager );
            spListItem.SetValue( Column.BranchName, BranchName );
            spListItem.SetValue( Column.CalendarDaysRemaining, CalendarDaysRemaining );
            spListItem.SetValue( Column.CalendarMonthsRemainingInCurrentYear, CalendarMonthsRemainingInCurrentYear );
            spListItem.SetValue( Column.City, City );
            spListItem.SetValue( Column.CostSavingsType, CostSavingsType );
            spListItem.SetValue( Column.DaysInProcess, DaysInProcess );
            spListItem.SetValue( Column.DaysOld, DaysOld );
            spListItem.SetValue( Column.DaysProcessedDaysProposed, DaysProcessedDaysProposed );
            spListItem.SetValue( Column.DaysProposed, DaysProposed );
            spListItem.SetValue( Column.DivisionCode, DivisionCode );
            spListItem.SetValue( Column.EAU, EAU );
            spListItem.SetValue( Column.EstimatedTotalMonthlySavings, EstimatedTotalMonthlySavings );
            spListItem.SetValue( Column.EstimatedTotalSavings, EstimatedTotalSavings );
            spListItem.SetValue( Column.EstimatedTotalSavingsTotal, EstimatedTotalSavingsTotal );
            spListItem.SetValue( Column.ExpirationDate, ExpirationDate );
            spListItem.SetValue( Column.FutureRealDaysRemaining, FutureRealDaysRemaining );
            spListItem.SetValue( Column.FutureRealMonthsRemaining, FutureRealMonthsRemaining );
            spListItem.SetValue( Column.GroupCode, GroupCode );
            spListItem.SetValue( Column.ImplementationDate, ImplementationDate );
            spListItem.SetValue( Column.ImplementationStatus, ImplementationStatus );
            spListItem.SetValue( Column.InitiativeNo, InitiativeNo );
            spListItem.SetValue( Column.InitiativeTimeFrame, InitiativeTimeFrame );
            spListItem.SetValue( Column.InProcessDate, InProcessDate );
            spListItem.SetValue( Column.InProcessStatus, InProcessStatus );
            spListItem.SetValue( Column.LocationName, LocationName );
            spListItem.SetValue( Column.LocationNo, LocationNo.ToString( ) );
            spListItem.SetValue( Column.ManagerEMail, ManagerEMail );
            spListItem.SetValue( Column.NA_ManagerEmailAddress, NA_ManagerEmailAddress );
            spListItem.SetValue( Column.NA_ManagerName, NA_ManagerName );
            spListItem.SetValue( Column.NA_ManagerNo, NA_ManagerNo );
            spListItem.SetValue( Column.NA_ManagerPhone, NA_ManagerPhone );
            spListItem.SetValue( Column.ParentCustomerName, ParentCustomerName );
            spListItem.SetValue( Column.ParentCustomerNo, ParentCustomerNo.ToString( ) );
            spListItem.SetValue( Column.ProposedDate, ProposedDate );
            spListItem.SetValue( Column.ProposedStatus, ProposedStatus );
            spListItem.SetValue( Column.RealizationBalance, RealizationBalance );
            spListItem.SetValue( Column.RealizationBalance2, RealizationBalance2 );
            spListItem.SetValue( Column.RealizationDate, RealizationDate );
            spListItem.SetValue( Column.RejectionDate, RejectionDate );
            spListItem.SetValue( Column.RejectionReason_, RejectionReason_ );
            spListItem.SetValue( Column.RemainingCurrentYearBalance, RemainingCurrentYearBalance );
            spListItem.SetValue( Column.RemainingInitiativeBalance, RemainingInitiativeBalance );
            spListItem.SetValue( Column.Salesrep, Salesrep );
            spListItem.SetValue( Column.SalesrepEmailAddress, SalesrepEmailAddress );
            spListItem.SetValue( Column.SalesrepName, SalesrepName );
            spListItem.SetValue( Column.SalesrepPhone, SalesrepPhone );
            spListItem.SetValue( Column.SectorCode, SectorCode );
            spListItem.SetValue( Column.St, St );
            spListItem.SetValue( Column.Status, Status );
            spListItem.SetValue( Column.UnitSavings, UnitSavings );
            spListItem.SetValue( Column.YearEnd, YearEnd );
            spListItem.SetValue( Column.Zip, Zip );

            updateSelfAwareness( );

            spListItem.SystemUpdate( false );
        }

        void updateSelfAwareness( )
        {
            var displayUrl = spListItem.ParentList.Forms[ PAGETYPE.PAGE_DISPLAYFORM ].Url;
            //var displayUrlFull = string.Format( "{0}/{1}?ID={2}, View Source", spListItem.Web.Url, displayUrl, spListItem.ID );
            var displayUrlFull = string.Format( "<p><a href='{0}/{1}?ID={2}' target='_blank'>View Source</a></p>", spListItem.Web.Url, displayUrl, spListItem.ID );

            var editUrl = spListItem.ParentList.Forms[ PAGETYPE.PAGE_EDITFORM ].Url;
            //var editUrlFull = string.Format( "{0}/{1}?ID={2}, Edit Source", spListItem.Web.Url, editUrl, spListItem.ID );
            var editUrlFull = string.Format( "<p><a href='{0}/{1}?ID={2}' target='_blank'>Edit Source</a></p>", spListItem.Web.Url, editUrl, spListItem.ID );

            spListItem[ Column.InitiativeDisplayUrl ] = displayUrlFull;
            spListItem[ Column.InitiativeEditUrl ] = editUrlFull;
            spListItem[ Column.InitiativeListID ] = spListItem.ParentList.ID.ToString( );
            spListItem[ Column.InitiativeItemID ] = spListItem.UniqueId.ToString( );
        }

        #endregion Methods
    }
}